#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>
int ticket_number = 1000;
//引入锁pthread_mutex_t是一个结构体，采用宏PTHREAD_MUTEX_INITIALIZER
//一旦采取这种全局定义方法，就不再需要手动释放锁
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //初始化锁，互斥锁或者叫做互斥量

//采取定义局部的锁，就要手动释放
//int pthread_mutex_lock(pthread_mutex_t* mutex)
//int pthread_mutex_trylock(pthread_mutex_t* mutex)非阻塞版本，失败就让申请的线程直接返回执行其他代码
//int pthread_mutex_unlock(pthread_mutex_t mutex)
//申请锁的过程必须是原子的，竞争申请锁，多线程都必须先看到锁，锁本身就是临界资源
//成功：继续向后运行，访问临界区代码，访问临界区资源
//失败：阻塞挂起
//锁提供的能力，就是执行临界区的代码，有并行转换为串行

void* thread_function(void* args)
{
    std::string name = (char*)args;
    while(1)
    {
        pthread_mutex_lock(&lock);//设置锁
        if(ticket_number > 0)
        {
            usleep(1000);
            ticket_number--;
            std::cout << name << "抢到了票号" << ticket_number << std::endl;
            //制作更多的内核陷入，而进程切换的时间点：时间片、等待IO等的检查就在内核态返回用户态的时候
            pthread_mutex_unlock(&lock); //解开锁
        }
        else
        {
            pthread_mutex_unlock(&lock);
            break;
        }
    }
    return nullptr;
}

int main()
{
    pthread_t t1;
    pthread_t t2;
    pthread_t t3;
    pthread_t t4;

    pthread_create(&t1, nullptr, thread_function, (void*)"thread-1");
    pthread_create(&t2, nullptr, thread_function, (void*)"thread-2");
    pthread_create(&t3, nullptr, thread_function, (void*)"thread-3");
    pthread_create(&t4, nullptr, thread_function, (void*)"thread-4");

    pthread_join(t1, nullptr);
    pthread_join(t2, nullptr);
    pthread_join(t3, nullptr);
    pthread_join(t4, nullptr);

    return 0;
}
